package com.qf.security.config;

import com.qf.core.constant.URLConstant;
import com.qf.security.exception.NoAuthenticationEntryPoint;
import com.qf.security.filter.UsernamePasswordJsonAuthenticationFilter;
import com.qf.security.handler.CustomAccessDeniedHandler;
import com.qf.security.handler.LoginFailHandler;
import com.qf.security.handler.LoginSuccessHandler;
import com.qf.security.jwt.filter.JwtAuthenticationTokenFilter;
import com.qf.security.utils.SingletonRegistry;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @Author: sin
 * @Date: 2025/5/5 20:40
 * @Description: Security配置类
 **/
@Slf4j
@Configuration
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {

    @Resource
    private MyauthorizationManager authorizationManager;

    @Resource
    private AuthenticationConfiguration authenticationConfiguration;

    @Resource
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    /**
     * Spring Security 主过滤链配置（Spring Security 6 推荐方式）
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http
                // 配置访问控制
                .authorizeHttpRequests(auth -> {
                    auth.requestMatchers(URLConstant.PERMIT_ALL_URLS).permitAll()
                            .anyRequest().access(authorizationManager);
                })
                .headers(h -> h.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
                .exceptionHandling(ex -> ex
                        .accessDeniedHandler(new CustomAccessDeniedHandler()) // 权限不足
                        // 配置身份验证异常处理
                        .authenticationEntryPoint(new NoAuthenticationEntryPoint())
                )
                // 添加自定义登录 JSON 认证过滤器
                .addFilterAt(usernamePasswordJsonAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                //
//            .addFilterAt(customLogoutFilter(),LogoutFilter.class)
                // jwt拦截器
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
                // 禁用默认 logout，使用自定义 filter
                .logout(AbstractHttpConfigurer::disable)
                // 关闭 CSRF 和 CORS（如有需要可开启）
                .csrf(AbstractHttpConfigurer::disable)
                .cors(AbstractHttpConfigurer::disable);
        return http.build();
    }

    /**
     * 获取认证管理器
     */
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    /**
     * 自定义登录拦截器
     */
    @Bean
    UsernamePasswordJsonAuthenticationFilter usernamePasswordJsonAuthenticationFilter() throws Exception {
        UsernamePasswordJsonAuthenticationFilter authenticationFilter = new UsernamePasswordJsonAuthenticationFilter();
        authenticationFilter.setAuthenticationSuccessHandler(new LoginSuccessHandler());
        authenticationFilter.setAuthenticationFailureHandler(new LoginFailHandler());
        authenticationFilter.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager());
        return authenticationFilter;
    }

    /**
     * 密码加密器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return SingletonRegistry.getInstance().getPasswordEncoder();
    }
}